import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { message, Modal } from 'ant-design-vue'
import { createVNode } from 'vue'

/**
 * @desc 脱敏
 * @param value 值
 * @param start  脱敏开始索引
 * @param end  结束索引
 */
export const desensitization = (value: string, start: number, end: number): string => {
  if (!value) return ''
  return value.replace(new RegExp(`^(.{${start - 1}})(.{${end - start + 1}})(.+)$`), (result, $1, $2, $3) => {
    return $1 + Array.from({ length: $2.length + 1 }).join('*') + $3
  })
}

/**
 * 保留n位小数
 * @param value 值，
 * @param n 小数位数
 * @param isFllZero 位数不够是否自动补零
 * @returns String
 */
export const toFixed = (value: number | string, n: number, isFllZero?: boolean) => {
  isFllZero = isFllZero === undefined ? true : isFllZero
  const f = Math.round(Number(value) * 10 ** n) / 10 ** n
  if (isFllZero && n > 0) {
    let s = f.toString()
    const rs = s.indexOf('.')
    if (rs === -1) {
      s += '.'
    }
    for (let i = s.length - s.indexOf('.'); i <= n; i++) {
      s += '0'
    }
    return s
  }
  return f.toString()
}

/**
 * 字符千分位分隔 支持负数 小数
 * @param value 值，
 * @returns String
 */
export const thousandSeparator = (value: number | string) => {
  return value
    .toString()
    .replaceAll(/,*/g, '')
    .replace(/\d+/, (str: string) => {
      return str.replaceAll(/-?(?=(\B\d{3})+$)/g, ',')
    })
}

/**
 * 清除非 数字和小数点的字符
 * @param value 值，
 * @returns String
 */
export const clearNotNumber = (value: number | string) => {
  return (value || '')
    .toString()
    .replaceAll(/[^\d.]/g, '')
    .toString()
}

/**
 * @description 深度克隆
 * @param {T} obj 需要深度克隆的对象
 * @returns {T} 克隆后的对象或者原值（非对象）
 */
export const cloneDeep = <T>(obj: T): T => {
  // 常见的非值直接返回（null、undefined、NaN、false）
  if ([false, null, Number.NaN, undefined].includes(obj as any)) return obj
  if (typeof obj !== 'object' || obj === null) {
    // 非对象或 null 直接返回
    return obj
  }
  const o: any = Array.isArray(obj) ? [] : {}
  // 遍历对象或数组属性，递归处理
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      o[key] = typeof obj[key] === 'object' && obj[key] !== null ? cloneDeep(obj[key]) : obj[key]
    }
  }
  return o
}

/**
 * @description JS 对象深度合并
 * @param {T} target 合并目标对象
 * @param {...any[]} sources 拷贝的来源对象
 * @returns {T} 返回深度合并后的目标对象
 */
export const mergeDeep = <T extends Record<string, any>>(target: T = {} as T, ...sources: any[]): T => {
  // 确保 target 为对象类型
  if (Object.prototype.toString.call(target) !== '[object Object]') return target
  target = cloneDeep(target) // 克隆 target，避免修改原始对象

  const combine = (source: any) => {
    for (const key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        const _target: any = target
        // 如果目标和源都是对象，则递归合并
        if (Object.prototype.toString.call(target[key]) === '[object Object]' && Object.prototype.toString.call(source[key]) === '[object Object]') {
          _target[key] = mergeDeep(target[key], source[key])
        }
        // 如果目标和源都是数组，则合并数组
        else if (Array.isArray(target[key]) && Array.isArray(source[key])) {
          _target[key] = [...new Set([...source[key], ...target[key]])] // 去重合并
        }
        // 其他情况直接赋值
        else {
          _target[key] = source[key]
        }
      }
    }
  }

  // 处理所有 sources 对象
  sources.forEach((source) => combine(source))

  return target
}

/**
 * 进行延时，以达到可以简写代码的目的 比如: await sleep(20)将会阻塞20ms
 * @param {number} value 堵塞时间 单位ms 毫秒
 * @returns {Promise} 返回promise
 */
export const sleep = (value = 30) => {
  return new Promise((resolve: any) => {
    setTimeout(() => {
      resolve()
    }, value)
  })
}

/**
 * 防抖
 * @param func 用户传入需要防抖的函数
 * @param wait  等待时间
 * @param flag  flag(布尔值):是否需要第一次触发事件立即执行(不传入flag则默认为false,不会立即执行第一次)
 */
export const debounce = (func: any, wait = 300, flag = false) => {
  let timer: any = null
  return (args?: any) => {
    const callNow = flag && !timer
    if (callNow) func.call(this, args)
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      if (!flag) func.call(this, args)
    }, wait)
  }
}

/**
 * 节流
 * @param func 用户传入需要节流的函数
 * @param wait  等待时间
 */
export const throttle = (func: any, wait = 50) => {
  let lastTime = 0
  return (...args: any) => {
    const nowTime = Date.now()
    if (nowTime - lastTime > wait) {
      lastTime = nowTime
      func.call(this, args)
    }
  }
}

/**
 * 根据blob下载文件
 */
export const downloadFileByBlob = (blob: Blob, fileName: string) => {
  const url = window.URL.createObjectURL(new Blob([blob]))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.setAttribute('download', fileName)
  document.body.append(link)
  link.click()
  link.remove()
}

// 抽离的通用导出方法
export const handleExport = async (exportFunction: Function, fileName: string, confirmMessage: string, additionalData?: any) => {
  Modal.confirm({
    title: '提示',
    icon: createVNode(ExclamationCircleOutlined),
    content: confirmMessage,
    okText: '确认',
    cancelText: '取消',
    centered: true,
    onOk: async () => {
      try {
        const response: any = await exportFunction({ data: additionalData })
        downloadFileByBlob(response, fileName)
      } catch (error: any) {
        const result = await error.response.data.text()
        const msg = JSON.parse(result).details
        message.error(msg)
      }
    }
  })
}
